package vip.xiaonuo.biz.modular.user.service.impl;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.dev33.satoken.stp.SaLoginModel;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import vip.xiaonuo.auth.core.util.StpClientUtil;
import vip.xiaonuo.biz.modular.fzrole.entity.BizFzRole;
import vip.xiaonuo.biz.modular.fzrole.service.BizFzRoleService;
import vip.xiaonuo.biz.modular.user.entity.BizFzUser;
import vip.xiaonuo.biz.modular.user.entity.BizUser;
import vip.xiaonuo.biz.modular.user.mapper.BizFzUserMapper;
import vip.xiaonuo.biz.modular.user.mapper.BizUserMapper;
import vip.xiaonuo.biz.modular.user.param.*;
import vip.xiaonuo.biz.modular.user.service.BizFzUserService;
import vip.xiaonuo.common.exception.CommonException;
import vip.xiaonuo.common.page.CommonPageRequest;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 分账用户表Service接口实现类
 *
 * @author gtc
 *
 **/
@Slf4j
@Service
public class BizFzUserServiceImpl extends ServiceImpl<BizFzUserMapper, BizFzUser> implements BizFzUserService {

    @Autowired
    private WxMaService wxMaService;

    @Autowired
    private BizFzRoleService bizFzRoleService;

    @Autowired
    private BizFzUserMapper bizFzUserMapper;

    @Autowired
    private BizUserMapper bizUserMapper;

    @Override
    public Page<BizFzUser> page(BizFzUserPageParam bizFzUserPageParam) {
        QueryWrapper<BizFzUser> queryWrapper = new QueryWrapper<>();
        if(ObjectUtil.isNotEmpty(bizFzUserPageParam.getName())) {
            queryWrapper.lambda().like(BizFzUser::getName, bizFzUserPageParam.getName());
        }
        if(ObjectUtil.isNotEmpty(bizFzUserPageParam.getPhone())) {
            queryWrapper.lambda().like(BizFzUser::getPhone, bizFzUserPageParam.getPhone());
        }
        if(ObjectUtil.isNotEmpty(bizFzUserPageParam.getStatus())) {
            queryWrapper.lambda().eq(BizFzUser::getStatus, bizFzUserPageParam.getStatus());
        }
        if(ObjectUtil.isNotEmpty(bizFzUserPageParam.getFzRole())) {
            queryWrapper.lambda().eq(BizFzUser::getFzRole, bizFzUserPageParam.getFzRole());
        }
        if(ObjectUtil.isNotEmpty(bizFzUserPageParam.getFzType())) {
            queryWrapper.lambda().eq(BizFzUser::getFzType, bizFzUserPageParam.getFzType());
        }
        return this.page(CommonPageRequest.defaultPage(), queryWrapper);
    }

    @Override
    public void add(BizFzUserAddParam bizFzUserAddParam) {
        BizFzUser bizFzUser = BeanUtil.toBean(bizFzUserAddParam, BizFzUser.class);
        this.save(bizFzUser);
    }

    @Override
    public void edit(BizFzUserEditParam bizFzUserEditParam) {
        BizFzUser bizFzUser = this.queryEntity(bizFzUserEditParam.getId());
        BeanUtil.copyProperties(bizFzUserEditParam, bizFzUser);
        this.updateById(bizFzUser);
    }

    @Override
    public void delete(List<BizFzUserIdParam> bizFzUserIdParamList) {
        for (BizFzUserIdParam bizFzUserIdParam : bizFzUserIdParamList) {
            BizFzUser bizFzUser = this.queryEntity(bizFzUserIdParam.getId());
            this.removeById(bizFzUser);
        }
    }

    @Override
    public BizFzUser detail(BizFzUserIdParam bizFzUserIdParam) {
        return this.queryEntity(bizFzUserIdParam.getId());
    }

    @Override
    public BizFzUser queryEntity(String id) {
        BizFzUser bizFzUser = this.getById(id);
        if(ObjectUtil.isEmpty(bizFzUser)) {
            throw new CommonException("分账用户不存在，id值为：{}", id);
        }
        return bizFzUser;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean bindWxOpenId(BizFzUserWxBindParam param) {
        try {
            // 1. 查询用户是否存在
            BizFzUser bizFzUser = this.queryEntity(param.getUserId());

            // 2. 通过code获取微信openid
            WxMaJscode2SessionResult sessionInfo = wxMaService.getUserService().getSessionInfo(param.getCode());
            String openid = sessionInfo.getOpenid();

            if (cn.hutool.core.util.StrUtil.isBlank(openid)) {
                throw new CommonException("获取微信openid失败");
            }

            log.info("微信小程序绑定分账用户，用户ID: {}, openid: {}", param.getUserId(), openid);

            // 3. 检查openid是否已被其他用户绑定
            QueryWrapper<BizFzUser> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(BizFzUser::getOpenId, openid);
            BizFzUser existUser = this.getOne(queryWrapper);

            if (existUser != null && !existUser.getId().equals(param.getUserId())) {
                log.warn("微信openid已被其他分账用户绑定，openid: {}, 已绑定用户ID: {}", openid, existUser.getId());
                throw new CommonException("该微信账号已被其他用户绑定");
            }

            // 4. 更新当前用户的openid
            bizFzUser.setOpenId(openid);
            boolean result = this.updateById(bizFzUser);

            if (result) {
                log.info("分账用户微信绑定成功，用户ID: {}", param.getUserId());
            } else {
                log.error("分账用户微信绑定失败，用户ID: {}", param.getUserId());
            }

            return result;
        } catch (CommonException e) {
            throw e;
        } catch (Exception e) {
            log.error("绑定微信openid异常", e);
            throw new CommonException("绑定微信openid异常: " + e.getMessage());
        }
    }

    @Override
    public Map<String, Object> wxLogin(BizFzUserWxLoginParam param) {
        try {
            log.info("微信小程序登录，code: {}", param.getCode());

            // 1. 通过code获取微信openid
            WxMaJscode2SessionResult sessionInfo = wxMaService.getUserService().getSessionInfo(param.getCode());
            String openid = sessionInfo.getOpenid();

            if (cn.hutool.core.util.StrUtil.isBlank(openid)) {
                throw new CommonException("获取微信openid失败");
            }

            // 2. 根据openid查询分账用户
            QueryWrapper<BizFzUser> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(BizFzUser::getOpenId, openid);
            BizFzUser user = bizFzUserMapper.selectOne(queryWrapper);

            if (user == null) {
                log.warn("微信openid未绑定分账用户，openid: {}", openid);
                return null;
            }

            // 3. 检查用户状态
            if (!"ENABLE".equals(user.getStatus())) {
                log.warn("分账用户已被禁用，用户ID: {}", user.getId());
                throw new CommonException("该分账用户已被禁用");
            }

            // 4. 生成token
            //利用sa-token完成登陆
            StpClientUtil.login(user.getId(), new SaLoginModel().setDevice("MINI").setExtra("id", user.getId()));
            // 缓存用户信息，此处使用TokenSession为了指定时间内无操作则自动下线
            StpClientUtil.getTokenSession().set("clientLoginUser", user);
            StpClientUtil.getSession().set("wxuser", JSONUtil.toJsonStr(user));
            String token = StpClientUtil.getTokenInfo().tokenValue;

            // 5. 构建返回结果
            Map<String, Object> result = new HashMap<>();
            // 过滤密码
            user.setPassword(null);
            result.put("user", user);
            result.put("token", token);

            log.info("微信小程序登录成功，用户ID: {}, 用户名: {}", user.getId(), user.getName());
            return result;
        } catch (CommonException e) {
            throw e;
        } catch (Exception e) {
            log.error("微信小程序登录异常", e);
            throw new CommonException("微信小程序登录异常: " + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> register(BizFzUserRegisterParam param) {
        try {
            log.info("注册分销用户，code: {}, roleValue: {}, invitationId: {}",
                    param.getCode(), param.getRoleValue(), param.getInvitationId());

            // 1. 通过code获取微信openid
            WxMaJscode2SessionResult sessionInfo = wxMaService.getUserService().getSessionInfo(param.getCode());
            String openid = sessionInfo.getOpenid();

            if (cn.hutool.core.util.StrUtil.isBlank(openid)) {
                throw new CommonException("获取微信openid失败");
            }

            // 2. 检查openid是否已被注册
            QueryWrapper<BizFzUser> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(BizFzUser::getOpenId, openid);
            BizFzUser existUser = this.getOne(queryWrapper);

            BizUser bizUser = bizUserMapper.selectOne(new LambdaQueryWrapper<BizUser>()
                    .eq(BizUser::getOpenId, openid));
            if (null != bizUser ) {
                if ("normal".equals(bizUser.getUserType())) {
                    bizUser.setUserType("fz");
                    bizUserMapper.updateById(bizUser);
                }
            } else {
                // 创建普通用户
                bizUser = new BizUser();
                bizUser.setOpenId(openid);
                bizUser.setStatus("ENABLE");
                bizUser.setUserType("fz");
                bizUserMapper.insert(bizUser);
            }

            if (existUser != null) {
                log.warn("该微信账号已注册，openid: {}, 用户ID: {}", openid, existUser.getId());
                //throw new CommonException("该微信账号已注册");
                String token = StpClientUtil.getTokenInfo().tokenValue;
                // 已存在用户直接返回用户信息
                Map<String, Object> result = new HashMap<>();
                result.put("user", bizUser);
                result.put("token", token);
                result.put("openId", openid);
                return result;
            }

            // 3. 根据roleValue获取角色信息
            BizFzRole role = null;


            // 4. 创建新用户
            BizFzUser newUser = new BizFzUser();
            newUser.setName(param.getNickName());
            newUser.setAvatar(param.getAvatarUrl());
            newUser.setOpenId(openid);
            newUser.setStatus("ENABLE"); // 默认启用

            // 设置邀请人ID
            if (ObjectUtil.isNotEmpty(param.getInvitationId())) {
                // 验证邀请人是否存在
                BizFzUser inviter = this.getById(param.getInvitationId());
                if (inviter == null) {
                    log.warn("邀请人不存在，invitationId: {}", param.getInvitationId());
                    //throw new CommonException("邀请人不存在");
                }
                newUser.setParentId(param.getInvitationId());
                // 二级分销人 reoleValue通过邀请人的roleValue去获取下级
                QueryWrapper<BizFzRole> roleQueryWrapper = new QueryWrapper<>();
                roleQueryWrapper.lambda().eq(BizFzRole::getRoleValue, inviter.getFzRole());
                BizFzRole role1 = bizFzRoleService.getOne(roleQueryWrapper);
                if (role1 != null) {
                    // 查询对应的二级分销角色
                    QueryWrapper<BizFzRole> roleQueryWrapper2 = new QueryWrapper<>();
                    roleQueryWrapper2.lambda().eq(BizFzRole::getParentId, role1.getId());
                    BizFzRole role2 = bizFzRoleService.getOne(roleQueryWrapper2);
                    if (role2 != null) {
                        role = role2;
                    } else {
                        log.warn("二级角色不存在，roleValue: {}", param.getRoleValue());
                        //throw new CommonException("不存在二级角色");
                    }
                }
            } else {
                newUser.setParentId("0"); // 默认无邀请人
                // 一级分销人 roleValue是前端传进来的
                QueryWrapper<BizFzRole> roleQueryWrapper = new QueryWrapper<>();
                roleQueryWrapper.lambda().eq(BizFzRole::getRoleValue, param.getRoleValue());
                role = bizFzRoleService.getOne(roleQueryWrapper);

                if (role == null) {
                    log.warn("角色不存在，roleValue: {}", param.getRoleValue());
                    //throw new CommonException("角色不存在");
                }
            }


            newUser.setFzRole(role.getRoleValue());
            newUser.setFzType(role.getFzType());
            newUser.setFzValue(role.getFzValue());

            // 5. 保存用户
            boolean saveResult = this.save(newUser);
            if (!saveResult) {
                log.error("保存用户失败");
                throw new CommonException("注册失败");
            }

//            // 通过openid检测是否有普通用户账户
//            BizUser bizUser = bizUserMapper.selectOne(new LambdaQueryWrapper<BizUser>()
//                    .eq(BizUser::getOpenId, openid));
//            if (null != bizUser && bizUser.getUserType().equals("normal")) {
//                bizUser.setUserType("fz");
//                bizUserMapper.updateById(bizUser);
//            } else {
//                // 创建普通用户
//                bizUser = new BizUser();
//                bizUser.setOpenId(openid);
//                bizUser.setStatus("ENABLE");
//                bizUser.setUserType("fz");
//                bizUserMapper.insert(bizUser);
//            }

            // 6. 生成token
            //利用sa-token完成登陆
            StpClientUtil.login(newUser.getId(), new SaLoginModel().setDevice("MINI").setExtra("id", newUser.getId()));
            // 缓存用户信息，此处使用TokenSession为了指定时间内无操作则自动下线
            StpClientUtil.getTokenSession().set("clientLoginUser", newUser);
            StpClientUtil.getSession().set("wxuser", JSONUtil.toJsonStr(newUser));
            String token = StpClientUtil.getTokenInfo().tokenValue;

            // 7. 构建返回结果
            Map<String, Object> result = new HashMap<>();
            result.put("user", bizUser);
            result.put("token", token);
            result.put("openId", openid);


            log.info("注册分销用户成功，用户ID: {}, 用户名: {}", newUser.getId(), newUser.getName());
            return result;
        } catch (CommonException e) {
            e.printStackTrace();
            throw e;
        } catch (Exception e) {
            log.error("注册分销用户异常", e);
            throw new CommonException("注册分销用户异常: " + e.getMessage());
        }
    }

    @Override
    public String login(ClientUserLoginParam loginParam) {
        LambdaQueryWrapper<BizFzUser> wrapper = new LambdaQueryWrapper<BizFzUser>().eq(BizFzUser::getPhone, loginParam.getPhone());
        BizFzUser user = this.getOne(wrapper);//查询用户是否存在
        if (ObjectUtil.isNull(user)){
            throw new CommonException("用户不存在");
        }
        if (ObjectUtil.notEqual(user.getPassword(),loginParam.getPassword())){
            throw new CommonException("密码不正确");
        }
//        if (ObjectUtil.equal(ClientUserStatusEnum.DISABLED.getValue(),user.getStatus())){
//            throw new CommonException("账户已被封禁");
//        }
        //利用sa-token完成登陆
        StpClientUtil.login(user.getId(), new SaLoginModel().setDevice("MINI").setExtra("id", user.getId()));
        // 缓存用户信息，此处使用TokenSession为了指定时间内无操作则自动下线
        StpClientUtil.getTokenSession().set("clientLoginUser", user);
        StpClientUtil.getSession().set("wxuser", JSONUtil.toJsonStr(user));
        return StpClientUtil.getTokenInfo().tokenValue;
    }
}
